package org.jacp.demo.util;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import java.util.WeakHashMap;

import javax.swing.JPanel;

import org.jacp.api.action.IAction;
import org.jacp.api.action.IActionListener;
import org.jacp.demo.globals.GlobalSettings;
import org.jacp.demo.ui.handler.ImageTransferHandler;
import org.jacp.demo.ui.listeners.DropShadowPanelMouseListener;

public class DropShadowPanel extends JPanel {

	/**
	 * 
	 */
	private static final long serialVersionUID = 6248122947742967401L;
	public static String KEY_BLUR_QUALITY = "blur_quality";
	public static String VALUE_BLUR_QUALITY_FAST = "fast";
	public final static int THUMB_WIDTH = GlobalSettings.THUMBNAIL_LONGER_SIDE;
	public final static int THUMB_HEIGHT = GlobalSettings.THUMBNAIL_SHORTER_SIDE;

	private VolatileImage finalImage;
	private VolatileImage clearPixel;

	public static final WeakHashMap<String, BufferedImage> shadowCache = new WeakHashMap<String, BufferedImage>();

	protected float angle = 30;
	protected int distance = 5;

	public static int shadowSize = 5;
	public static float shadowOpacity = 0.5f;
	public static Color shadowColor = Color.BLACK;

	// cached values for fast painting
	public static int distance_x = 0;
	public static int distance_y = 0;

	protected String filePath = "";
	private String fileName = "";

	private final Dimension preferredSize = new Dimension(
			GlobalSettings.SHADOW_PANEL_WIDTH,
			GlobalSettings.SHADOW_PANEL_HEIGHT);

	protected IActionListener<ActionListener, ActionEvent, Object> listener;

	protected String target;

	private boolean thumbnailSet = false;

	protected DropShadowPanel() {
		computeShadowPosition();
		setTransferHandler(new ImageTransferHandler());
		addMouseListener(new DropShadowPanelMouseListener());
	}

	public DropShadowPanel(final VolatileImage finalImage,
			final VolatileImage clearPixel, final String filePath) {
		computeShadowPosition();
		setTransferHandler(new ImageTransferHandler());
		addMouseListener(new DropShadowPanelMouseListener(filePath, this));
		this.finalImage = finalImage;
		this.clearPixel = clearPixel;
		setFilePath(filePath);
		fileName = this.filePath.substring(filePath.lastIndexOf("/") + 1,
				filePath.length());

	}

	public String getFilePath() {
		return filePath;
	}

	public void setFilePath(final String filePath) {
		this.filePath = filePath;
	}

	@Override
	public Dimension getPreferredSize() {
		return preferredSize;
	}

	public void setImage(final VolatileImage image) {
		finalImage = image;
	}

	public float getAngle() {
		return angle;
	}

	public void setAngle(final float angle) {
		this.angle = angle;
		computeShadowPosition();
	}

	public int getDistance() {
		return distance;
	}

	public void setDistance(final int distance) {
		this.distance = distance;
		computeShadowPosition();
	}

	public Color getShadowColor() {
		return shadowColor;
	}

	public float getShadowOpacity() {
		return shadowOpacity;
	}

	public int getShadowSize() {
		return shadowSize;
	}

	private void computeShadowPosition() {
		final double angleRadians = Math.toRadians(angle);
		distance_x = (int) (Math.cos(angleRadians) * distance);
		distance_y = (int) (Math.sin(angleRadians) * distance);
	}

	@Override
	protected void paintComponent(final Graphics g) {
		g.drawImage(finalImage, 0, 0, null);
		g.drawString(fileName, 5, 110);
	}

	public IActionListener<ActionListener, ActionEvent, Object> getListener() {
		return listener;
	}

	public void setListener(
			final IActionListener<ActionListener, ActionEvent, Object> listener) {
		this.listener = listener;
	}

	public String getTarget() {
		return target;
	}

	public void setTarget(final String target) {
		this.target = target;
	}

	/**
	 * handle double click from mouse listener and notify full screen component
	 * to show selected image
	 */
	public void handleDoubleClick() {
		final IAction<ActionEvent, Object> myAction = getListener().getAction();
		myAction.addMessage(target, filePath);
		getListener().getListener().actionPerformed(myAction.getActionEvent());
	}

	public boolean isThumbnailSet() {
		return thumbnailSet;
	}

	public void setThumbnailSet(final boolean thumbnailSet) {
		this.thumbnailSet = thumbnailSet;
	}

	public final void clear() {
		this.setThumbnailSet(false);
		this.finalImage = clearPixel;
		this.repaint();
	}

}
